
export const MSG_TYPE = {
  HEART: 'survival',
  WS_READY: 'wsReady',
  ID_CARD: 'id',
  QRCode: 'bar',
  KEY_BOARD: 'kb',
  PRINT_NOTICE: 'print',
  QUEUE_CHANGE: 'queueChange',
  CONFIG_CHANGE: 'configChange',
}

const createHeartMsg = (uuid) => {
  return {
    type: MSG_TYPE.HEART,
    data: {
      uuid,
    }
  }
}

class MyWebsocket {
  websocket = null;
  eventMap = new Map();
  onceEventMap = {};
  heartTimer = 0;
  heartDeily = 15 * 1000;
  deily = 5 * 1000; // 重连延迟等等延迟
  reconnect = 5; // 重连次数
  constructor(url) {
    this.url = url;
    this.init();
  }
  on(key, callback) {
    if (this.eventMap.has(key)) {
      const list = this.eventMap.get(key);
      list.push(callback);
    } else {
      this.eventMap.set(key, [callback]);
    }
  }
  once(key, callback) {
    this.onceEventMap[key] = callback;
  }
  send(msg) {
    if (this.websocket.readyState === 1) {
      this.websocket.send(JSON.stringify(msg));
    } else {
      this.on(MSG_TYPE.WS_READY, () => {
        this.send(msg)
      });
    }
  }
  heart() {
    this.heartTimer = setInterval(() => {
      this.send(createHeartMsg(this.uuid));
    }, this.heartDeily);
  }
  init() {
    if (!this.url.startsWith('ws')) {
      return;
    }
    this.websocket = new WebSocket(this.url);

    this.websocket.onopen = () => {
      this.heart();
      this.emit(MSG_TYPE.WS_READY);
    }
    this.websocket.onmessage = (msg) => {
      const { data } = msg;
      // eg: 字符串，需要 JSON.parse
      // data: {"type":"idCard","data":123456789123}
      try {
        if (data) {
          const { code, type, data: msgData, msg } = JSON.parse(data);
          if (code && code !== 200) {
            console.error(msg);
          } else {
            this.emit(type, msgData);
          }
        }
      } catch (error) {
        // console.log(error);
        this.emit('', data);
      }
    }
    this.websocket.onerror = (ev) => {
      this.close();
    }
    this.websocket.onclose = () => {
      this.close();
      setTimeout(() => {
        this.init();
      }, this.deily);
    }
  }
  close() {
    clearTimeout(this.heartTimer);
    this.websocket.close();
  }
  emit(type, ...args) {
    const eventList = this.eventMap.get(type);
    if (eventList && eventList.length) {
      eventList.forEach((event) => {
        event(...args);
      });
    }
    if (this.onceEventMap[type]) {
      this.onceEventMap[type](...args);
      delete this.onceEventMap[type]
    }
  }
}


export class CommonWS extends MyWebsocket {
  static instance;
  constructor(options) {
      super(options);
  }
  static getInstance(options) {
      if (!this.instance) {
          this.instance = new CommonWS(options);
      }
      return this.instance;
  }
  static updataWsInstance(options) {
      this.instance = new CommonWS(options);
  }
}

export default (url) => {
  let ws = CommonWS.getInstance(url);
  return ws;
}